﻿#include "MyFrame.h"


MyFrame::MyFrame()
	: wxFrame(NULL, wxID_ANY, "文件夹整理工具"), mainPanel(nullptr)
{
	// 创建新面板
	mainPanel = new wxPanel(this, wxID_ANY);

	CreateStatusBar();
	SetStatusText("欢迎使用文件整理工具！");

	CreateUI();
}

void MyFrame::CreateUI()
{
	// 为整个面板设置字体
	//wxFont defaultFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
	wxFont systemFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); // 获取系统默认字体
	//mainPanel->SetFont(defaultFont);
	systemFont.SetPointSize(12); // 将字体设为12磅
	mainPanel->SetFont(systemFont);

	wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

	// 计算所有类别名称的最大宽度
	int maxLabelWidth = 0;
	wxClientDC dc(mainPanel);
	dc.SetFont(mainPanel->GetFont());

	for (const auto& pair : fileTypeMap) {
		wxString labelText = pair.first + ":";
		wxSize textSize = dc.GetTextExtent(labelText);
		if (textSize.GetWidth() > maxLabelWidth) {
			maxLabelWidth = textSize.GetWidth();
		}
	}

	// 添加一些边距
	maxLabelWidth += 20;

	// 遍历map，为每个类别创建一行UI
	for (auto it = fileTypeMap.begin(); it != fileTypeMap.end(); ++it)
	{
		wxString category = it->first;
		const std::vector<wxString>& exts = it->second;

		// 水平Sizer：标签 + 文本框 + 按钮
		wxBoxSizer* hSizer = new wxBoxSizer(wxHORIZONTAL);

		// 类别标签 - 设置固定宽度
		wxStaticText* label = new wxStaticText(mainPanel, wxID_ANY, category + ":");
		label->SetMinSize(wxSize(maxLabelWidth, -1));  // 固定宽度，高度自适应

		hSizer->Add(label, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 10);

		// 扩展名文本框
		wxString extStr;
		for (size_t i = 0; i < exts.size(); ++i) {
			extStr += exts[i];
			if (i != exts.size() - 1) extStr += ", ";
		}
		wxTextCtrl* extCtrl = new wxTextCtrl(mainPanel, wxID_ANY, extStr,
			wxDefaultPosition, wxSize(600, -1),
			wxTE_READONLY);

		hSizer->Add(extCtrl, 1, wxEXPAND | wxRIGHT, 5);  // 使用EXPAND和比例1


		// 修改名称按钮
		wxButton* renameBtn = new wxButton(mainPanel, wxID_ANY, "修改名称");
		hSizer->Add(renameBtn, 0, wxRIGHT, 5);
		renameBtn->Bind(wxEVT_BUTTON, [this, oldCategory = it->first](wxCommandEvent& event) {
			wxString newName = wxGetTextFromUser(
				"请输入新的类别名称：",
				"修改类别名称",
				oldCategory,
				this
			);

			if (!newName.IsEmpty() && newName != oldCategory) {
				// 更新逻辑
				// 使用迭代器修改key（需要先删除再插入新项）
				auto it = fileTypeMap.find(oldCategory);
				if (it != fileTypeMap.end()) {
					std::vector<wxString> exts = it->second;
					fileTypeMap.erase(it);
					fileTypeMap[newName] = exts;
				}
				// 刷新UI
				RefreshUI();
			}
			});

		// 增加扩展名按钮
		wxButton* addBtn = new wxButton(mainPanel, wxID_ANY, "增加扩展名");
		hSizer->Add(addBtn, 0);
		addBtn->Bind(wxEVT_BUTTON, [this, category = it->first](wxCommandEvent& event) {
			wxString newExt = wxGetTextFromUser(
				"请输入新的扩展名",
				"增加扩展名",
				"",
				this
			);

			if (!newExt.IsEmpty()) {
				// 更新逻辑
				newExt = newExt.Lower();
				if (fileTypeMap.find(category) != fileTypeMap.end()) {
					auto& exts = fileTypeMap[category];
					// 检查是否已存在
					if (std::find(exts.begin(), exts.end(), newExt) == exts.end()) {
						exts.push_back(newExt);
					}
				}
				// 刷新UI
				RefreshUI();
			}
			});

		mainSizer->Add(hSizer, 0, wxEXPAND | wxALL, 5);
	}

	// 创建按钮
	wxButton* dirChooseBtn = new wxButton(mainPanel, wxID_ANY, "选择文件夹");
	mainSizer->Add(dirChooseBtn, 0, wxALL | wxALIGN_CENTER_HORIZONTAL, 10);
	// 为“选择文件夹”按钮绑定事件
	dirChooseBtn->Bind(wxEVT_BUTTON, &MyFrame::OnBtnDirChooser, this);

	mainPanel->SetSizer(mainSizer);

	SetStatusText("欢迎使用文件整理工具！");

	SetMinSize(wxSize(600, 320));

	Center();
}

void MyFrame::RefreshUI()
{
	if (mainPanel) {
		mainPanel->DestroyChildren();

		CreateUI();

		mainPanel->Layout();
	}
}

void MyFrame::OnBtnDirChooser(wxCommandEvent& event) {
	wxDirDialog dirDialog(
		this,
		"请选择目标文件夹",
		wxEmptyString,
		wxDD_DEFAULT_STYLE
	);

	if (dirDialog.ShowModal() == wxID_OK) {
		wxString path = dirDialog.GetPath();
		// 在主窗口状态栏显示选中的路径（与主窗口关联）
		SetStatusText("选中的文件夹：" + path);

		// 调用文件处理函数
		organizeWithLogging(path);
	}
}

void MyFrame::organizeWithLogging(const wxString& directory)
{
	std::string dirStr = directory.ToStdString();
	fs::path logDir = fs::path(dirStr) / "文件整理日志";
	if (!fs::exists(logDir)) {
		createDirectory(logDir.string());
	}
	std::string timestamp = getTimeStrForFilename(); // 获取时间戳作为日志文件后缀
	std::string logFileName = "文件整理日志_" + timestamp + ".txt";
	fs::path logPath = logDir / logFileName;
	std::ofstream logFile(logPath);

	// 先创建所有分类目录
	for (const auto& pair : fileTypeMap) {
		std::string category = pair.first.ToStdString();
		fs::path categoryDir = fs::path(dirStr) / category;
		
		if (createDirectory(categoryDir.string())) {
			logFile << "目录 " << categoryDir.string() << " 已创建或已存在\n";
		}
		else {
			logFile << "目录 " << categoryDir.string() << " 创建失败\n";
		}
	}
	// 创建 Others 目录
	fs::path othersDir = fs::path(dirStr) / "Others";
	if (createDirectory(othersDir.string())) {
		logFile << "目录 " << othersDir.string() << " 已创建或已存在\n\n\n";
	}
	else {
		logFile << "目录 " << othersDir.string() << " 创建失败\n\n\n";
	}

	fs::path rootPath(dirStr);
	for (const auto& entry : fs::directory_iterator(dirStr)) {
		// 跳过目录
		if (entry.is_directory()) {
			continue;
		}

		// 只处理普通目录
		if (entry.is_regular_file()) {
			// 确保文件在根目录下（双重检查）
			if (entry.path().parent_path() != rootPath) {
				continue;
			}

			std::string category = determineCategory(entry.path().extension().string());
			fs::path targetPath = fs::path(dirStr) / category / entry.path().filename();

			// 跳过已经在正确目录的文件
			if (entry.path().parent_path() == targetPath.parent_path()) continue;

			if (moveFile(entry.path().string(), targetPath.string())) {
				std::cout << "成功: " << entry.path() << " -> " << category << "\n";
				logFile << "成功: " << entry.path() << " -> " << category << "\n";
			}
			else if (fs::exists(targetPath.string())) {
				std::cout << "文件已存在: " << entry.path() << "\n";
				logFile << "文件已存在: " << entry.path() << "\n";
			}
			else {
				std::cout << "失败: " << entry.path() << "\n";
				logFile << "失败: " << entry.path() << "\n";
			}
		}
	}

	logFile.close();

	wxMessageBox("文件整理完成！", "完成", wxOK | wxICON_INFORMATION, this);
}

bool MyFrame::createDirectory(const std::string& path) {
	try {
		// 检查目录是否已存在
		if (fs::exists(path) && fs::is_directory(path)) {
			return true;
		}
		return fs::create_directories(path); // 创建目录并返回结果
	}
	catch (const fs::filesystem_error& e) {
		std::cerr << "创建目录失败: " << path << " - " << e.what() << "\n";
		return false;
	}
	catch (...) {
		std::cerr << "未知错误创建目录: " << path << "\n";
		return false;
	}
}

std::string MyFrame::determineCategory(const std::string& extension) {
	std::string extLower = extension;
	std::transform(extLower.begin(), extLower.end(), extLower.begin(), ::tolower);

	for (const auto& pair : fileTypeMap) {
		auto it = std::find(pair.second.begin(), pair.second.end(), extLower);
		if (it != pair.second.end()) {
			return pair.first.ToStdString();
		}
	}
	return "Others";
}

bool MyFrame::moveFile(const std::string& source, const std::string& destination) {
	try {
		// 检查目标文件是否已存在
		if (fs::exists(destination)) {
			std::cout << "文件已存在: " << destination << "\n";
			return false;
		}

		// 确保目标目录存在
		fs::path destPath(destination);
		createDirectory(destPath.parent_path().string());

		fs::rename(source, destination);
		return true;
	}
	catch (const fs::filesystem_error& e) {
		std::cerr << "移动文件失败: " << e.what() << std::endl;
		// 如果跨设备移动失败，使用复制+删除的方式
		try {
			fs::copy(source, destination);
			fs::remove(source);
			return true;
		}
		catch (const std::exception& copyEx) {
			std::cerr << "文件复制仍然失败: " << copyEx.what() << "\n";
			return false;
		}
		catch (...) {
			return false;
		}
	}
}

std::string MyFrame::getTimeStrForFilename()
{
	// 获取当前时间（时间点）
	auto now = std::chrono::system_clock::now();
	// 转为 C 风格的 time_t 类型，以便后续格式化
	std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
	// 转为本地时间（包含年月日时分秒的结构）
	std::tm local_tm = *std::localtime(&now_time_t);

	std::ostringstream oss;
	oss << std::put_time(&local_tm, "%Y%m%d_%H%M%S");
	return oss.str();
}